#include "input.h"

#include "hash.h"
#include "messagecontroller.h"

#include <fstream>
#include <map>
#include <string>


using namespace fortress;

inputController::inputController() : 
messages(messageController::getInstance()),
running(1),
save(0)
{
	
}

inputController::~inputController()
{

}

void inputController::getMapping(char const *filename)
{
	std::string *line = new std::string;
	std::string key;
	std::string value;
	std::ifstream FILE;
	FILE.open(filename);
	if (FILE.is_open())
	{
		while (!FILE.eof())
		{
			std::getline(FILE, *line);
			key=line->substr(0,line->find_first_of('=',0));	// Set key to everything before an equals sign
			value=line->substr(line->find_first_of('=',0)+1,line->length()-1);	// Set value to everything after the equals sign
			int keyInt;
			if (key.length()==1)
			{
				keyInt=static_cast<int>(key[0]);
			}
			else
			{
				// Casting from a const char * to an int
				keyInt=(int)(key.c_str());	// Hopefully the file includes a key number value
			}
			// Get the hash value of the loaded command
			mappedInput.insert(std::pair<int, int>(keyInt,hash::getHash(value)));
		}
	}
	else
	{
		throw (std::string("Could not open file for input!"));
		// Do a log manager thing TODO
	}
	delete line;
}

bool inputController::isRunning()
{
	return running;
}

void inputController::stop(bool savegame)
{
	running=0;
	save=savegame;
}

bool inputController::doSave()
{
	return save;
}

void inputController::setControlled(eventReceiver *setCharacter)
{
	controlledCharacter = setCharacter;
}

bool inputController::translateInput(TCOD_key_t keypress)
{
	if (keypress.vk==TCODK_CHAR)
	{
		moveDirections dir=m_invalid;
		bool hasDirection=0;
		int action;
		if (savedKey.vk==TCODK_CHAR)
		{
			savedKey.vk=TCODK_NONE;
			hasDirection=1;
			action=mappedInput[savedKey.c];
			dir=readDirection(mappedInput[keypress.c]);
		}
		else
		{
			action=mappedInput[keypress.c];
		}
		hash &compare = hash::getInstance();
		// Quit
		if (action==compare.quit)
		{
			stop(0);
			return 0;
		}
		else if (action==compare.save)
		{
			stop(1);
			return 0;
		}
		else if (action==compare.open || action==compare.close)
		{
			if (!hasDirection)
			{
				getDirection(keypress);
				return 0;
			}
			else
			{
				playerEvents doEvent;
				if (action==compare.open)
				{
					doEvent=event_open;
				}
				else if (action==compare.close)
				{
					doEvent=event_close;
				}
				else
				{
					throw (std::string("Expected a directioned event type, but it did not match the list of event types with directions."));
				}

				if (dir==m_invalid)
				{
					messageController & messages = messageController::getInstance();
					messages.addMessage("Invalid direction.");
					return 0;
				}
				else
				{
					return controlledCharacter->exec(doEvent, dir);
				}
			}
		}
		else if (action==compare.upstairs || action==compare.downstairs)
		{
			return controlledCharacter->exec(event_stairs, action==compare.upstairs);
		}
		else if (action==compare.pickup)
		{
			return controlledCharacter->exec(event_pickup,0);
		} 
		else if (action==compare.drop)
		{
			// yeah, gonna have to do some more work here
			return controlledCharacter->exec(event_drop,0);
		}
		else if (action==compare.inventory)
		{
			return controlledCharacter->exec(event_inventory,0);
		}
		else
		{
			// move
			moveDirections dir = readDirection(action);
			if (dir != m_invalid)
			{
				return controlledCharacter->exec(event_move, dir);
			}
		}		
	}
	return 0;
}

moveDirections inputController::readDirection(int input)
{
	hash &compare = hash::getInstance();
	if (input==compare.move_n)
	{
		return m_north;
	}
	else if (input==compare.move_ne)
	{
		return m_northeast;
	}
	else if (input==compare.move_e)
	{
		return m_east;
	}
	else if (input==compare.move_se)
	{
		return m_southeast;
	}
	else if (input==compare.move_s)
	{
		return m_south;
	}
	else if (input==compare.move_sw)
	{
		return m_southwest;
	}
	else if (input==compare.move_w)
	{
		return m_west;
	}
	else if (input==compare.move_nw)
	{
		return m_northwest;
	}
	return m_invalid;
}

void inputController::getDirection(TCOD_key_t keypress)
{
	// Let the input function and the player know that we're now looking for a directional input
	messages.addMessage("Please select a direction.");
	savedKey=keypress;
	
//	TCOD_key_t key=TCODConsole::waitForKeypress(true);
//	int dir = mappedInput[key.c];
//	return readDirection(dir);
}

bool inputController::waitForInput()
{
	TCOD_key_t key;
	key.vk=TCODK_NONE;
	while (key.vk == TCODK_SHIFT || key.vk == TCODK_NONE)
	{
		key=TCODConsole::waitForKeypress(true);
	}
	
	return translateInput(key);
	// do something with this keypress
}

void inputController::waitForKeypress()
{
	TCODConsole::waitForKeypress(true);
}